texture SplatTexture;
texture NormalTexture;
texture BaseTexture;
texture RTexture;
texture GTexture;
texture BTexture;
texture ATexture;

float4x4 WorldViewProjection : WORLDVIEWPROJ;
float4x4 WorldView : WORLDVIEW;

float3 LightVectorZUp = normalize(float3(1, 2, 3));

float FogDistance <
  string UIName = "Fog Distance";
  float UIMin = 10;
  float UIMax = 10000;
> = 2000;

float4 FogColor <
  string UIName = "Fog Color";
  string UIType = "ColorSwatch";
> = float4(0.7, 0.7, 0.7, 1);

//  Making this bigger means that alpha coverage in splat layers 
//  turns more into alpha testing, and less like alpha blending.
//  That's often useful because the alpha value ramps smoothly 
//  between 0 and 1 otherwise.
float HardLines = 10;

sampler SplatSampler = 
sampler_state
{
  Texture = <SplatTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 2;
};

sampler NormalSampler = 
sampler_state
{
  Texture = <NormalTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 2;
};

sampler BaseSampler = 
sampler_state
{
  Texture = <BaseTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 4;
};

sampler RSampler = 
sampler_state
{
  Texture = <RTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 4;
};

sampler GSampler = 
sampler_state
{
  Texture = <GTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 4;
};

sampler BSampler = 
sampler_state
{
  Texture = <BTexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 4;
};

sampler ASampler = 
sampler_state
{
  Texture = <ATexture>;
  MipFilter = LINEAR;
  MinFilter = ANISOTROPIC;
  MagFilter = ANISOTROPIC;
  MaxAnisotropy = 4;
};


struct VS_OUTPUT
{
  float4 Position   : POSITION;   // vertex position 
  float2 TextureUV  : TEXCOORD0;  // vertex texture coords 
  float Fog : COLOR0;
};


VS_OUTPUT RenderSceneVS( float4 vPos : POSITION, 
                         float2 vTexCoord0 : TEXCOORD0)
{
  VS_OUTPUT Output;
  
  // Transform the position from object space to homogeneous projection space
  Output.Position = mul(vPos, WorldViewProjection);
 
  // Just copy the texture coordinate through
  Output.TextureUV = vTexCoord0;

  Output.Fog = 1 - saturate(length(mul(vPos, WorldView)) / FogDistance);

  return Output;
}


struct PS_OUTPUT
{
  float4 RGBColor : COLOR0;  // Pixel color    
};


PS_OUTPUT RenderScenePS( VS_OUTPUT In ) 
{ 
  PS_OUTPUT Output;

  float4 splat = tex2D(SplatSampler, In.TextureUV);
  float4 base = tex2D(BaseSampler, In.TextureUV * 45);
  float4 r = tex2D(RSampler, In.TextureUV * 44);
  float4 g = tex2D(GSampler, In.TextureUV * 43);
  float4 b = tex2D(BSampler, In.TextureUV * 42);
  float4 a = tex2D(ASampler, In.TextureUV * 41);
  float3 n = tex2D(NormalSampler, In.TextureUV) * 2 - float3(1, 1, 1);

  splat.r = saturate(splat.r * (HardLines+1) + r.a * HardLines - HardLines);
  splat.g = saturate(splat.g * (HardLines+1) + g.a * HardLines - HardLines);
  splat.b = saturate(splat.b * (HardLines+1) + b.a * HardLines - HardLines);
  splat.a = saturate(splat.a * (HardLines+1) + a.a * HardLines - HardLines);
  float fullWeight = dot(splat, float4(1, 1, 1, 1));
  float total = max(fullWeight, 1);
  splat = splat / total;
  float4 val = base * (1 - min(fullWeight, 1));
  float ndotl = saturate(dot(normalize(n), LightVectorZUp)) * 0.8f + 0.2f;
  val += r * splat.r;
  val += g * splat.g;
  val += b * splat.b;
  val += a * splat.a;

  float4 c = val * ndotl;;
  Output.RGBColor = lerp(FogColor, c, In.Fog);

  return Output;
}

technique RenderScene
{
  pass P0
  {
    AlphaBlendEnable = FALSE;
    ZEnable          = TRUE;
    ZWriteEnable     = TRUE;
    CullMode         = CW;
    VertexShader = compile vs_2_0 RenderSceneVS();
    PixelShader  = compile ps_2_0 RenderScenePS(); 
  }
}